﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;

namespace StarsAdmin.Core.Extensions.Json.Converters
{
    /// <summary>
    /// 移出空数组
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class NullArrayConverter<T> : JsonConverter
    {
        private readonly bool _isRemoveNullArray;

        /// <summary>
        /// 移出空数组，
        /// 默认将空数组转换为null,否则移出这个属性
        /// </summary>
        /// <param name="isRemoveNullArray">默认将空数组转换为null,否则移出这个属性</param>
        public NullArrayConverter(bool isRemoveNullArray = false)
        {
            _isRemoveNullArray = isRemoveNullArray;
        }

        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(T);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value == null)
            {
                writer.WriteNull();
            } else
            {
                JsonSerializer jsonSerializer = new JsonSerializer()
                {
                    // 忽略循环引用
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                    // 设置时间格式
                    DateFormatString = "yyyy-MM-dd HH:mm:ss",
                    //设置返回小写属性
                    ContractResolver = new CamelCasePropertyNamesContractResolver(),
                    // 设置空值不返回
                    NullValueHandling = NullValueHandling.Ignore,
                    DefaultValueHandling = DefaultValueHandling.Ignore,
                };
                JToken jobject = GetChildren(JToken.FromObject(value, jsonSerializer));
                serializer.Serialize(writer, jobject);
            }
        }

        private JToken GetChildren(JToken jToken)
        {
            if (jToken is JObject jobject)
            {
                foreach (var property in jobject.Properties().ToList())
                {
                    if (property.Value.Type == JTokenType.Array && !property.Value.HasValues)
                    {
                        if (_isRemoveNullArray)
                        {
                            jobject.Remove(property.Name);
                        } else
                        {
                            property.Value = null;
                        }
                    } else
                    {
                        GetChildren(property.Value);
                    }
                }
            } else if (jToken is JArray jArray)
            {
                for (int i = 0; i < jArray.Count(); i++)
                {
                    if (jArray[i].Type == JTokenType.Array && !jArray[i].HasValues)
                    {
                        if (_isRemoveNullArray)
                        {
                            jArray.RemoveAt(i);
                        } else
                        {
                            jArray.Value<string>(null);
                        }
                    } else
                    {
                        GetChildren(jArray[i]);
                    }
                }
            }
            return jToken;
        }
    }

    /// <summary>
    /// 将空数组转换为null
    /// <code>使用方法 : 标记在DTO属性上</code>
    /// </summary>
    public class NullArrayConverter : JsonConverter<object[]>
    {
        public override object[] ReadJson(JsonReader reader, Type objectType, object[] existingValue, bool hasExistingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override void WriteJson(JsonWriter writer, object[] value, JsonSerializer serializer)
        {
            if (value.Length == 0)
            {
                writer.WriteNull();
            } else
            {
                serializer.Serialize(writer, value);
            }
        }
    }
}